package com.divemotor.ventarepuestosinternet.dao.impl;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.divemotor.ventarepuestosinternet.beans.adapter.ClienteAdapter;
import com.divemotor.ventarepuestosinternet.beans.form.ClienteBeanForm;
import com.divemotor.ventarepuestosinternet.dao.ClienteDAO;
import com.divemotor.ventarepuestosinternet.model.Cliente;
import com.divemotor.ventarepuestosinternet.util.Constantes;
import com.divemotor.ventarepuestosinternet.util.Paginacion;

@Repository(value="clienteDAO")
@SuppressWarnings("unchecked")
public class ClienteDAOImpl  implements ClienteDAO, Serializable{

	private static final long serialVersionUID = 1L;
	
	@Autowired
	private SessionFactory sessionFactory;
	
	public Cliente getReferencia(String idCliente){
		return (Cliente)sessionFactory.getCurrentSession().load(Cliente.class, idCliente);
	}
	
	@Override
	public List<Cliente> listarTodos() {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Cliente.class);
		criteria.add(Restrictions.not(Restrictions.isNull(("idCliente"))));
		return criteria.list();
	}
	
	@Override
	public List<Cliente> listarClientes(Cliente cliente) {	
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Cliente.class);
		construirRestriccionClientes(cliente, criteria);
		return criteria.list();
	}

	@Override
	public Integer cantidadClientes(ClienteBeanForm clienteBuscar) {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Cliente.class);
        criteria.setProjection(Projections.count("idCliente"));
        construirRestriccionClientes(clienteBuscar, criteria);
		return ((Number) criteria.uniqueResult()).intValue();
	}

	
	@Override
	public List<ClienteAdapter> listar(Paginacion paginacion) {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Cliente.class, "cliente");
		criteria.add(Restrictions.not(Restrictions.isNull(("cliente.idCliente"))));
		criteria.setFirstResult(paginacion.getInicioPagina());
		criteria.setMaxResults(paginacion.getFinPagina());
		
		construirProyeccion(criteria);
		construirRestriccionClientes(paginacion.getCliente(), criteria);
		
		if (paginacion.getOrdenarLabel() != null) {
			criteria.addOrder(paginacion.getDireccionOrden().equals(Constantes.ORDEN_DEFAULT) ? Order.asc(paginacion.getOrdenarLabel()) : 
				  														 		   				Order.desc(paginacion.getOrdenarLabel()) );
		} else {
			criteria.addOrder(Order.asc("nombre"));
		}
		
		criteria.setResultTransformer(Transformers.aliasToBean(ClienteAdapter.class));
		return criteria.list();
	}
	
	private void construirProyeccion(Criteria criteria){
		ProjectionList lista = Projections.projectionList();
		lista.add(Projections.property("idCliente"), "idCliente");
		lista.add(Projections.property("nombre"), "nombre");
		lista.add(Projections.property("dni"), "dni");
		lista.add(Projections.property("ruc"), "ruc");
		lista.add(Projections.property("tipoPersona"), "tipoPersona");
		lista.add(Projections.property("direccion"), "direccion");
		criteria.setProjection(lista);
	}
	
	private void construirRestriccionClientes(ClienteBeanForm clienteBuscar, Criteria criteria) {
		construirRestriccion(clienteBuscar.getRuc(), clienteBuscar.getDni(), clienteBuscar.getNombre(), criteria);
	}
	
	private void construirRestriccionClientes(Cliente clienteBuscar, Criteria criteria) {
		construirRestriccion(clienteBuscar.getRuc(), clienteBuscar.getDni(), clienteBuscar.getNombre(), criteria);
	}
	
	private void construirRestriccion(String ruc, String dni, String nombre, Criteria criteria){
		String porc = Constantes.PORCENTAJE;
		
		if(StringUtils.isNotBlank(ruc)){
			criteria.add(Restrictions.like("ruc", porc + ruc + porc).ignoreCase());
		}
		
		if(StringUtils.isNotBlank(dni)){
			criteria.add(Restrictions.like("dni", porc + dni + porc).ignoreCase());
		}
		
		if(StringUtils.isNotBlank(nombre)){
			criteria.add(Restrictions.like("nombre",porc + nombre + porc).ignoreCase());
		}
	}
	
}
